<!doctype html>
<html style="height:100%;font-size:14px;">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" type="text/css" href="./gc.spread.sheets.excel2013white.13.0.0.css">
    <script src="https://cdn.grapecity.com.cn/spreadjs/scripts/jquery-1.11.1.min.js" type="text/javascript"></script>
    <script src="./gc.spread.sheets.all.13.0.0.min.js" type="text/javascript"></script>
    <script src="./gc.spread.sheets.shapes.13.0.0.min.js" type="text/javascript"></script>
    <script src="./gc.spread.sheets.resources.zh.13.0.0.min.js" type="text/javascript"></script>

    <script src="./data.js" type="text/javascript"></script>
    <style>
        * {
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        }

        .sample-tutorial {
            position: relative;
            height: 100%;
            overflow: hidden;
        }
    </style>
</head>

<body style="margin:0;position:absolute;top:0;bottom:0;left:0;right:0;font-size:14px;user-select:none;-webkit-user-select: none;overflow:hidden;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'">
    <div class="sample-tutorial">
        <div id="ss" style="width:100%;height:100%"></div>
    </div>
    <script type="text/javascript">
        var gcNS = GC.Spread.Sheets;
        var BAR_HEIGHT = 30,
            FORZEN_WIDTH = 0,
            DEFAULT_ROW_HEIGHT = 35;
        var GANNT_COLUMN_WIDTH = 300;
        var maxLevelNum = 2;
        //bar color
        var colorBox = ["#d7bde5", "#3f7c50", "#c84028", "#6642b3", "#3866ba", "#FF69B4", "#e17000", "#c84028"];
        //progessBar color
        var progessColorBox = ["#ebdff1", "#a1bfa9", "#e4a094", "#b3a1d9", "#9fb6dd", "#fbcdaa", "#7FFFAA", "#CD6155"];
        var colorIndex = 0,
            colorProgessIndex = 0;


        window.onload = function() {
            var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
            spread.options.scrollByPixel = true;
            spread.options.scrollPixel = 3;
            var createGanntView = new CreateGannt(spread);
            createGanntView.init();
        }

        var CreateGannt = (function() {
            function CreateGannt(spread) {
                this.spread = spread;
            }
            CreateGannt.prototype.init = function() {
                var sheet = this.spread.getActiveSheet();
                this.spread.suspendPaint();
                this.processData();
                this.bindData(sheet);
                this.initSheetView(sheet, this.spread);
                this.generateGanntFormula(sheet);
                this.processGenerateGanntData(sheet);
                this.addCellBorder(sheet);
                this.progessBindValue(sheet);
                this.spread.resumePaint();
            };
            CreateGannt.prototype.progessBindValue = function(sheet) {
                sheet.bind(GC.Spread.Sheets.Events.CellChanged, function(e, target) {
                    if (target.col === 4) {
                        if (parseFloat(target.newValue).toString() === "NaN" ||
                            (parseFloat(target.newValue).toString() !== "NaN" && (target.newValue > 1 || target.newValue < 0))) {
                            sheet.setValue(target.row, target.col, target.oldValue);
                        } else {
                            sheet.shapes.get("gannt" + target.row + dataSource[target.row].id).text(
                                dataSource[target.row].id + "  " +
                                (parseFloat(GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, "Sheet1!$E$" + (target.row + 1))) * 100).toFixed(1) +
                                "%"
                            )
                        }
                    }
                });
            };
            CreateGannt.prototype.addCellBorder = function(sheet) {
                for (var i = 0; i < dataSource.length; i++) {
                    var range = sheet.getRange(i, 0, 1, 1, 2);
                    var range1 = sheet.getRange(i, 1, 1, 1, 3);
                    if (dataSource[i].group) {
                        range.borderRight(new gcNS.LineBorder(dataSource[i].color, gcNS.LineStyle.thick));
                        range1.borderLeft(new gcNS.LineBorder(dataSource[i].color, gcNS.LineStyle.thick));
                    } else {
                        range.borderRight(new gcNS.LineBorder(dataSource[i].color, gcNS.LineStyle.thin));
                        range1.borderLeft(new gcNS.LineBorder(dataSource[i].color, gcNS.LineStyle.thin));
                    }
                }
            };
            CreateGannt.prototype.processData = function() {
                var color, progessColor;
                for (var i = 0; i < dataSource.length; i++) {
                    var dataRow = dataSource[i];
                    if (maxLevelNum < dataRow.indent) {
                        maxLevelNum = dataRow.indent;
                    }
                    if (dataSource[i + 1] && dataSource[i + 1].indent > dataRow.indent) {
                        dataRow.group = true;
                    }
                    if (!dataRow.end) {
                        dataRow.finish = true;
                    }
                    if (dataRow.group) {
                        if (colorIndex > 7) {
                            colorIndex = 0;
                            colorProgessIndex = 0;
                        }
                        color = colorBox[colorIndex++];
                        dataRow.color = color;
                        progessColor = progessColorBox[colorProgessIndex++];
                        dataRow.progessColor = progessColor;
                    } else {
                        dataRow.color = color;
                        dataRow.progessColor = progessColor;
                    }
                }
            };
            CreateGannt.prototype.bindData = function(sheet) {
                sheet.autoGenerateColumns = false;
                sheet.setDataSource(dataSource);
                var bindInfos = [{
                        name: "id",
                        displayName: "ID",
                        size: 110,
                        visible: false
                    },
                    {
                        name: "name",
                        displayName: "Task",
                        size: 200
                    },
                    {
                        name: "start",
                        displayName: "Start Date",
                        size: 90,
                        formatter: "dd-mmm"
                    },
                    {
                        name: "end",
                        displayName: "End Date",
                        size: 90,
                        formatter: "dd-mmm"
                    },
                    {
                        name: "progressValue",
                        displayName: "Duration",
                        size: 70
                    },
                    {
                        name: "connectTo",
                        displayName: "ConnectTo",
                        size: 200,
                        visible: false
                    },
                ];
                for (var row = 0, count = sheet.getRowCount(); row < count; row++) {
                    sheet.getCell(row, 1).textIndent(sheet.getDataItem(row).indent);
                }
                sheet.bindColumns(bindInfos);
                bindInfos.forEach(function(info) {
                    if (info.visible !== false) {
                        FORZEN_WIDTH += info.size;
                    }
                })
            };
            CreateGannt.prototype.initSheetView = function(sheet, spread) {
                spread.options.tabStripVisible = false;
                spread.options.showHorizontalScrollbar = false;
                var sheetAreaColHeader = gcNS.SheetArea.colHeader;
                sheet.outlineColumn.options({
                    columnIndex: 1,
                    showIndicator: true,
                    maxLevel: maxLevelNum,
                    expandIndicator: "",
                    collapseIndicator: ""
                });
                sheet.showRowOutline(false);

                var style = new GC.Spread.Sheets.Style();
                style.formatter = "0.0%";
                style.hAlign = 1;
                sheet.setStyle(-1, 4, style);

                var style1 = this.getDateTimeDropDowns();
                style1.hAlign = 1;
                sheet.setStyle(-1, 2, style1);
                sheet.setStyle(-1, 3, style1);
                sheet.setStyle(-1, 4, style);
                sheet.setStyle(-1, 4, style);

                sheet.defaults.rowHeight = DEFAULT_ROW_HEIGHT;
                var defaultStyle = sheet.getDefaultStyle();
                defaultStyle.vAlign = gcNS.VerticalAlign.center;
                sheet.setColumnCount(sheet.getColumnCount() + 4);
                sheet.setRowCount(2, sheetAreaColHeader);
                sheet.options.allowCellOverflow = false;
                sheet.frozenColumnCount(6)
                sheet.addSpan(0, 1, 2, 1, sheetAreaColHeader);
                sheet.addSpan(0, 2, 2, 1, sheetAreaColHeader);
                sheet.addSpan(0, 3, 2, 1, sheetAreaColHeader);
                sheet.addSpan(0, 4, 2, 1, sheetAreaColHeader);
                sheet.addSpan(0, 6, 1, 4, sheetAreaColHeader);
                sheet.setValue(0, 6, "2010 Q1", sheetAreaColHeader);
                sheet.setValue(1, 6, "January", sheetAreaColHeader);
                sheet.setValue(1, 7, "February", sheetAreaColHeader);
                sheet.setValue(1, 8, "March", sheetAreaColHeader);
                sheet.setValue(1, 9, "April", sheetAreaColHeader);

                sheet.setValue(0, 1, "Task", sheetAreaColHeader);
                sheet.setValue(0, 2, "Start", sheetAreaColHeader);
                sheet.setValue(0, 3, "End", sheetAreaColHeader);
                sheet.setValue(0, 4, "Progress", sheetAreaColHeader);
                var parent = sheet.getParent()
                parent.options.scrollbarMaxAlign = true
                for (var index = 6; index < 10; index++) {
                    sheet.setColumnWidth(index, GANNT_COLUMN_WIDTH);
                }
                spread.options.allowUserResize = false;
                spread.options.allowUserZoom = false;
            };
            CreateGannt.prototype.generateGanntFormula = function(sheet) {
                var sheetAreaColHeader = gcNS.SheetArea.colHeader,
                    spread = sheet.getParent();
                spread.addCustomName("GANNT_WIDTH_UNIT", '=' + GANNT_COLUMN_WIDTH * 4 / 119);
                spread.addCustomName("FIXED_DATAVIEW_OFFSET", '=' + FORZEN_WIDTH);
                //@ is the place holder to apply row index.
                var assistantColumns = [{
                        col: 10,
                        value: "X",
                        formula: 'DATEDIF(DATE(YEAR(C@),1,1),C@,"YD")*GANNT_WIDTH_UNIT+FIXED_DATAVIEW_OFFSET'
                    },
                    {
                        col: 11,
                        value: "Y",
                        formula: '(ROW()-1)*' + (DEFAULT_ROW_HEIGHT) + "+15"
                    },
                    {
                        col: 12,
                        value: "Width",
                        formula: 'IFERROR(DATEDIF(C@,D@,"YD"),0)*GANNT_WIDTH_UNIT'
                    },
                ];
                sheet.addColumns(sheet.getColumnCount(), assistantColumns.length);
                assistantColumns.forEach(function(colInfo) {
                    sheet.setValue(0, colInfo.col, colInfo.value, sheetAreaColHeader);
                    sheet.setColumnVisible(colInfo.col, true);
                    sheet.setFormatter(-1, colInfo.col, "00.0");
                    for (var row = 0, count = sheet.getRowCount(); row < count; row++) {
                        sheet.setFormula(row, colInfo.col, colInfo.formula.replace(/@/g, row + 1));
                    }
                });
                //hide calculating data 
                sheet.setColumnWidth(10, 0);
                sheet.setColumnWidth(11, 0);
                sheet.setColumnWidth(12, 0);
            };
            CreateGannt.prototype.processGenerateGanntData = function(sheet) {
                var rowCount = sheet.getRowCount();
                var ganntData = [];
                for (var i = 0; i < rowCount; i++) {
                    var gannt = {
                        name: "gannt" + i,
                        height: 25
                    };
                    gannt.x = "=" + sheet.name() + "!" + GC.Spread.Sheets.CalcEngine.rangeToFormula(new GC.Spread.Sheets.Range(i, 10, 1, 1));
                    gannt.y = "=" + sheet.name() + "!" + GC.Spread.Sheets.CalcEngine.rangeToFormula(new GC.Spread.Sheets.Range(i, 11, 1, 1));
                    gannt.width = "=" + sheet.name() + "!" + GC.Spread.Sheets.CalcEngine.rangeToFormula(new GC.Spread.Sheets.Range(i, 12, 1, 1));;
                    gannt.type = dataSource[i].group ? GC.Spread.Sheets.Shapes.AutoShapeType.leftArrow :
                        (dataSource[i].finish ? GC.Spread.Sheets.Shapes.AutoShapeType.flowchartDecision : GC.Spread.Sheets.Shapes.AutoShapeType.rectangle);
                    gannt.color = dataSource[i].color;
                    gannt.progessColor = dataSource[i].progessColor;
                    gannt.height = 15;
                    ganntData.push(gannt);
                }
                this.generateGanntBar(sheet, ganntData);
            };
            CreateGannt.prototype.getDateTimeDropDowns = function() {
                var style = new GC.Spread.Sheets.Style();
                style.cellButtons = [{
                    imageType: GC.Spread.Sheets.ButtonImageType.dropdown,
                    command: "openDateTimePicker",
                    useButtonStyle: false,
                    visibility: GC.Spread.Sheets.ButtonVisibility.onSelected
                }];
                style.hAlign = 1;
                style.formatter = "dd-mmm";
                style.dropDowns = [{
                    type: GC.Spread.Sheets.DropDownType.dateTimePicker,
                    option: {
                        showTime: false,
                    }
                }];
                return style;
            }
            CreateGannt.prototype.generateGanntBar = function(sheet, ganntInfos) {
                ganntInfos.forEach((ganntInfo, index) => {
                    var calcValue = GC.Spread.Sheets.CalcEngine.evaluateFormula;
                    var width = calcValue(sheet, ganntInfo.width),
                        shapeProgess;
                    if (ganntInfo.type) {
                        if (ganntInfo.type === 1) {
                            shapeProgess = sheet.shapes.add(ganntInfo.name + "shapeProgess", ganntInfo.type);
                            shapeProgess.x(ganntInfo.x);
                            shapeProgess.y(calcValue(sheet, ganntInfo.y) + 1);
                            shapeProgess.width(ganntInfo.width);
                            shapeProgess.height(ganntInfo.height - 2);
                            var styleProgess = shapeProgess.style();
                            styleProgess.fill.color = ganntInfo.progessColor;
                            styleProgess.fill.transparency = 0.05;
                            styleProgess.line.transparency = 0;
                            styleProgess.line.color = ganntInfo.color;
                            shapeProgess.style(styleProgess);
                            shapeProgess.allowResize(false);
                            shapeProgess.allowMove(false);
                        }
                        if (ganntInfo.type === 34) {
                            shapeProgess = sheet.shapes.add(ganntInfo.name + "shapeProgess", GC.Spread.Sheets.Shapes.AutoShapeType.leftRightArrow);
                            shapeProgess.x(ganntInfo.x);
                            shapeProgess.y(calcValue(sheet, ganntInfo.y));
                            shapeProgess.width(ganntInfo.width);
                            shapeProgess.height(ganntInfo.height + 5);
                            var styleProgess = shapeProgess.style();
                            styleProgess.fill.color = ganntInfo.progessColor;
                            styleProgess.fill.transparency = 0.05;
                            styleProgess.line.transparency = 0;
                            styleProgess.line.color = ganntInfo.color;
                            shapeProgess.style(styleProgess);
                            shapeProgess.allowResize(false);
                            shapeProgess.allowMove(false);
                        }
                        var shape = sheet.shapes.add(ganntInfo.name, ganntInfo.type);
                        shape.x(width === 0 ? (ganntInfo.x + "-10") : ganntInfo.x);
                        shape.y(ganntInfo.type === 34 ? calcValue(sheet, ganntInfo.y) :
                            (width === 0 ? calcValue(sheet, ganntInfo.y) - 5 : calcValue(sheet, ganntInfo.y) + 1));
                        shape.width(width === 0 ? ganntInfo.height + 14 : (ganntInfo.width + "*" + "Sheet1!$E$" + (index + 1)));
                        shape.height(ganntInfo.type === 34 ? ganntInfo.height + 5 : ganntInfo.height - 2);
                        var style = shape.style();
                        style.fill.color = width === 0 ? "#EEE685" : ganntInfo.color;
                        style.line.transparency = width === 0 ? 0 : 1;
                        style.line.color = width === 0 ? "#8B864E" : ganntInfo.color;
                        shape.style(style);

                        //add shape desc
                        if (dataSource[index]) {
                            var shape1 = sheet.shapes.add(ganntInfo.name + dataSource[index].id, GC.Spread.Sheets.Shapes.AutoShapeType.rectangle);
                            shape1.x(ganntInfo.x + "+" + parseInt(shape.width() / 2) + "+5");
                            shape1.y(calcValue(sheet, ganntInfo.y) - 19);
                            shape1.width(200);
                            shape1.height(30);
                            if (!dataSource[index].finish) {
                                shape1.text(dataSource[index].id + "  " + (dataSource[index].progressValue * 100).toFixed(1) + "%");
                            } else {
                                shape1.text("end");
                            }
                            var style1 = shape1.style();
                            style1.fill.transparency = 1;
                            style1.fill.color = "transparency";
                            style1.line.color = "transparency";
                            style1.textEffect.color = "gray";
                            style1.line.transparency = 1;
                            shape1.style(style1);
                        }
                        //add shape line
                        if (ganntInfo.type === 1 && ganntInfos[index + 1] && (ganntInfos[index + 1].type === 1 || ganntInfos[index + 1].type === 63)) {
                            var connectorShape = sheet.shapes.add('shapeLine' + dataSource[index].id, 41);
                            connectorShape.width(15);
                            connectorShape.height(15);
                            connectorShape.x(ganntInfos[index].x + "+" + "Sheet1!$M$" + (index + 1) + "+ 3");
                            connectorShape.y(calcValue(sheet, ganntInfos[index].y) + 11);
                            var connectorShapeStyle = connectorShape.style();
                            connectorShapeStyle.line.transparency = 1;
                            connectorShapeStyle.fill.color = "#A9A9A9";
                            connectorShapeStyle.line.transparency = 1;
                            connectorShape.style(connectorShapeStyle);
                            connectorShape.rotate(90);
                        }
                    }
                });
            }
            return CreateGannt;
        })();
    </script>
</body>

</html>